import numpy as np

class Vehicle:
    def __init__(self,box,vtype,key) -> None:
        self.key = key #车辆追踪key
        self.box = box #检测框 xyxy
        self.vtype = vtype #车辆类型，数字
        self.direction = 0 #正方向驶入, 默认0驶入,1驶出
        self.dx = np.array([(box[0]+box[2])/2,(box[1]+box[3])/2]) #中心点
        self.captured=False #未被抓拍，2帧后有位移了就进行抓拍，已经抓拍
        self.frames=0 #累计帧超过3帧且未被抓拍，视为失效车辆，由管理bus统一累加
        self.updated=True#已经进行了，更新由管理bus最后统一置false
        # 未进行更新的车辆在最后全部移除bus，认为已经脱离抓拍区域ROI。
        # 已经完成抓拍的车辆，继续累计即可，不再触发抓拍。 
    
    def update(self,box,positive_vec):
        # 手动进行更新的记得添加到抓拍触发列表
        self.box = box
        new_dx = np.array([(box[0]+box[2])/2,(box[1]+box[3])/2])
        self.direction = new_dx - self.dx
        self.dx = new_dx
        self.direction = 0 if np.dot(self.direction,positive_vec) > 0 else 1
        self.updated=True
        self.captured=True #触发或者保持已抓拍状态

    def get_iou(self,box,vtype):
        # 计算相似iou
        if self.vtype != vtype or self.updated:
            return 0
        return self.iou(self.box,box)
    
    @staticmethod
    def iou(box1: np.ndarray, box2: np.ndarray) -> float:
        """
        计算两个单独的框的 IOU
        box格式: [x1, y1, x2, y2]
        """

        # 计算交集坐标
        x_left = max(box1[0], box2[0])
        y_top = max(box1[1], box2[1])
        x_right = min(box1[2], box2[2])
        y_bottom = min(box1[3], box2[3])

        # 计算交集面积
        inter_width = max(0, x_right - x_left)
        inter_height = max(0, y_bottom - y_top)
        inter_area = inter_width * inter_height

        # 计算各自面积
        area1 = (box1[2] - box1[0]) * (box1[3] - box1[1])
        area2 = (box2[2] - box2[0]) * (box2[3] - box2[1])

        # 计算并集面积
        union_area = area1 + area2 - inter_area

        if union_area == 0:
            return 0.0

        # 计算IOU
        iou_value = inter_area / union_area
        return iou_value

